/*
 * author: VDaras
 */

#include "sdl/Surface.h"
#include "RenderLayer.h"
#include "Drawable.h"
#include "RenderingManager.h"
#include "sdl/GraphicsCore.h"

RenderLayer::RenderLayer()
{
    m_visible = true;
    m_factor = 1;
}

RenderLayer::RenderLayer(float distance)
{
    m_visible = true;
    m_factor = distance;
}

RenderLayer::~RenderLayer()
{
}

void RenderLayer::AddDrawable(Drawable *toAdd)
{
    m_drawables.insert(m_drawables.end(), toAdd);
    SortDrawables();
}

void RenderLayer::RemoveDrawable(Drawable* toRemove)
{
    for (unsigned int i = 0; i < m_drawables.size(); ++i)
    {
        if (m_drawables[i] == toRemove)
        {
            m_drawables.erase(m_drawables.begin() + i);
            return;
        }
    }
}

/*
 * Render drawables which are inside the camera pane
 */

void RenderLayer::Render(sdl::GraphicsCore* gCore, Camera *camera)
{
    unsigned int drawablesSize = m_drawables.size();

    if (!m_visible) return;
    if (drawablesSize == 0) return;
    unsigned int i;

    //second camera is used for parallax scrolling offset calculation
    Camera cam2 = Camera(*camera);
    cam2.SetFocus(cam2.GetRect()->GetLeft() * m_factor,
                  cam2.GetRect()->GetTop() * m_factor);

    for (i = 0; i < drawablesSize; ++i)
    {
        if (m_drawables[i]->IsVisible(cam2))
        {
            m_drawables[i]->Draw(gCore, &cam2);
        }
    }
    return;
}

void RenderLayer::SetVisibility(bool sVisible)
{
    m_visible = sVisible;
}

bool RenderLayer::ContainsDrawable(const Drawable* toTest) const
{

    for (std::vector<Drawable *>::const_iterator iter = m_drawables.begin(); iter != m_drawables.end(); ++iter)
    {
        if (*iter == toTest)
        {
            return true;
        }
    }

    return false;
}

/*
 * Sort drawables using insertion sort
 */

void RenderLayer::SortDrawables()
{
    int i, j;

    Drawable *key = NULL;

    int drawablesSize = static_cast<int> (m_drawables.size());

    for (j = 1; j < drawablesSize; ++j)
    {
        key = m_drawables[j];
        int keyTotalWidth = key->GetX() + key->GetWidth();

        for (i = j - 1; (i >= 0) && (m_drawables[i]->GetX() + m_drawables[i]->GetWidth() > keyTotalWidth); --i) // Smaller values move up
        {
            m_drawables[i + 1] = m_drawables[i];
        }

        m_drawables[i + 1] = key;
    }

}

float RenderLayer::GetFactor()
{
    return m_factor;
}
